home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / show / FV21BETA-src.lha / FV21BETA-src / FVasm.s < prev    next >
Text File  |  1998-10-29  |  41KB  |  2,052 lines

  1. ; Abbrevations used:
  2. ;
  3. ; RGB = 3 bytes per pixel (R,G,B) 24bit.
  4. ; FTC = 1 byte per pixel.  Fake True Color, the palette is set in such a way
  5. ;       that it acts as a 8bit (or less) true color mode.
  6.  
  7.     Opt    l+,case
  8.  
  9. MC68000    EQU    0
  10.  
  11.     XDef    _RANDOM
  12.     XDef    _RGBTOFTC
  13.     XDef    _DECODEGIF
  14.     XDef    _SCALERGB
  15.     XDef    _SCALEGRAY
  16.  
  17.     Incdir    "INCLUDE:"
  18.  
  19.     Include    "exec/types.i"
  20.     Include    "exec/nodes.i"
  21.  
  22.     Include    "FV.hi"
  23.  
  24. ToggleLed    MACRO
  25.     Move.l    d0,-(sp)
  26.     Moveq    #-1,d0
  27.     Bset    #1,$bfe001
  28. .Loop\@    Move.l    $0.l,$0.l
  29.     Dbra    d0,.Loop\@
  30.     Bclr    #1,$bfe001
  31.     Move.l    (sp)+,d0
  32.     ENDM
  33.  
  34.  
  35. ; seed = ((seed + 7) * 257) % (2^31-1)
  36.  
  37. ;$0ffff - $ffff   = $0000   =  $ffff + $0    = $ffff -> $0000
  38. ;$10000 - $ffff   = $0001   =  $0000 + $1    = $0001
  39. ;$1fffd - $ffff   = $fffe   =  $fffd + $1    = $fffe
  40. ;$1fffe - $ffff*2 = $0000   =  $fffe + $1    = $ffff -> $0000
  41. ;$1ffff - $ffff*2 = $0001   =  $ffff + $1    = $0000 + X = $0001
  42. ;$20000 - $ffff*2 = $0002   =  $0000 + $2    = $0002
  43. ;$2fffc - $ffff*2 = $fffe   =  $fffc + $2    = $fffe
  44. ;$2fffd - $ffff*3 = $0000   =  $fffd + $2    = $ffff -> $0000
  45. ;$2fffe - $ffff*3 = $0001   =  $fffe + $2    = $0000 + X = $0001
  46. ;$2ffff - $ffff*3 = $0002   =  $ffff + $2    = $0001 + X = $0002
  47. ;$30000 - $ffff*3 = $0003   =  $0000 + $3    = $0003
  48.  
  49. ;$07fff - $7fff   = $0000   =  $7fff + $0    = $7fff - $7fff = $0000
  50. ;$08000 - $7fff   = $0001   =  $0000 + $1    = $0001
  51. ;$0fffd - $7fff   = $7ffe   =  $7ffd + $1    = $7ffe
  52. ;$0fffe - $7fff*2 = $0000   =  $7ffe + $1    = $7fff - $7fff = $0000
  53. ;$0ffff - $7fff*2 = $0001   =  $7fff + $1    = $8000 - $7fff = $0001
  54. ;$10000 - $7fff*2 = $0002   =  $0000 + $2    = $0002
  55. ;$17ffc - $7fff*2 = $7ffe   =  $
  56. ;$17ffd - $7fff*3 = $0000   =  $7ffd + $2    = $7fff - $7fff = $0000
  57. ;$17ffe - $7fff*3 = $0001
  58. ;$17fff - $7fff*3 = $0002   =  $7fff + $2    = $8001 - $7fff = $0002
  59. ;$18000 - $7fff*3 = $0003   =  $0000 + $3    = $0003
  60.  
  61. ;$808505                    =  $0505 + $101  = $0606
  62.  
  63.     CNOP    0,4
  64. _RANDOM    ; IN: d0.l = Seed
  65.     ;OUT: d0.l = New seed
  66.  
  67.     Movem.l    d1-d3,-(sp)
  68.     Moveq    #0,d2
  69.     Move.l    d0,d3
  70.  
  71.     Moveq    #0,d1    d1:d0 = seed
  72.     Addq.l    #7,d0    d1:d0 = seed+7
  73.  
  74.     Rol.l    #8,d0
  75.     Move.b    d0,d1
  76.     Clr.b    d0    d1:d0 = (seed+7) * 256
  77.  
  78.     Add.l    d3,d0
  79.     Addx.w    d2,d1    d1:d0 = (seed+7) * 257
  80.  
  81.     Lsl.w    #1,d1    Make room for a bit.
  82.     Lsl.l    #1,d0    Shift highest bit into X.
  83.     Addx.w    d2,d1    Highest bit of d0 shifted into lowest bit of d1
  84.     Lsr.l    #1,d0    d0 is now automatically ANDed with $7fffffff
  85.  
  86.     Add.l    d1,d0
  87.     Move.l    #$7fffffff,d1
  88.     Cmp.l    d1,d0
  89.     Blo.s    .Done
  90.     Sub.l    d1,d0
  91.  
  92. .Done    Movem.l    (sp)+,d1-d3
  93.     Rts
  94.  
  95.  
  96.  
  97. ;    CNOP    0,4
  98. ;_RANDOM    ; IN: d0.l = Seed
  99. ;    ;OUT: d0.l = New seed
  100. ;    Movem.l    d1-d2,-(sp)
  101. ;
  102. ;    Moveq    #0,d1
  103. ;    Move.w    d0,d1
  104. ;    Clr.w    d0
  105. ;    Swap    d0
  106. ;
  107. ;    Move.l    d0,d2
  108. ;    Lsl.l    #8,d0
  109. ;    Add.l    d2,d0
  110. ;
  111. ;    Move.l    d1,d2
  112. ;    Lsl.l    #8,d1
  113. ;    Add.l    d2,d1
  114. ;
  115. ;    Move.l    d0,d2
  116. ;    Swap    d2
  117. ;    And.l    #$7fff0000,d2
  118. ;    Add.l    d2,d1
  119. ;    Bvc.s    .Skip
  120. ;    Addq.l    #1,d1
  121. ;
  122. ;.Skip    Moveq    #15,d2
  123. ;    Lsr.l    d2,d0
  124. ;    Add.l    d1,d0
  125. ;    Bclr    #31,d0
  126. ;
  127. ;    Movem.l    (sp)+,d1-d2
  128. ;    Rts
  129.  
  130.  
  131.  
  132.  
  133.     CNOP    0,4
  134. _SCALERGB    ; IN: a0.l = Input (RGB buffer)
  135.     ; IN: a1.l = Output (RGB buffer)
  136.     ; IN: d0.w = Width in pixels
  137.     ; IN: d1.w = Scalefactor (0-4095 for shrinking, 4096 for no scaling, 4097-32767 for enlarging)
  138.  
  139.     Movem.l    d0-d2/a0-a1,-(sp)
  140.     Move.w    #-2048,d2
  141.     Subq.w    #1,d0
  142.  
  143.     Cmp.w    #4096,d1
  144.     Bgt.s    .Enlarging
  145.  
  146. .Loop    Add.w    d1,d2
  147.     Blt.s    .GoLoop
  148.     Sub.w    #4096,d2
  149.     Move.b    (a0)+,(a1)+
  150.     Move.b    (a0)+,(a1)+
  151.     Move.b    (a0)+,(a1)+
  152.     Dbra    d0,.Loop
  153.     Bra.s    .Exit
  154. .GoLoop    Addq.l    #3,a0
  155.     Dbra    d0,.Loop
  156.     Bra.s    .Exit
  157.  
  158. .Enlarging    Add.w    d1,d2
  159. .Loop2    Move.b    (a0),(a1)+
  160.     Move.b    1(a0),(a1)+
  161.     Move.b    2(a0),(a1)+
  162.     Sub.w    #4096,d2
  163.     Bge.s    .Loop2
  164.     Addq.l    #3,a0
  165.     Dbra    d0,.Enlarging
  166.  
  167. .Exit    Movem.l    (sp)+,d0-d2/a0-a1
  168.     Rts
  169.  
  170.  
  171.  
  172.     CNOP    0,4
  173. _SCALEGRAY    ; IN: a0.l = Input (RGB buffer)
  174.     ; IN: a1.l = Output (RGB buffer)
  175.     ; IN: d0.w = Width in pixels
  176.     ; IN: d1.w = Scalefactor (0-4095 for shrinking, 4096 for no scaling, 4097-32767 for enlarging)
  177.  
  178.     Movem.l    d0-d2/a0-a1,-(sp)
  179.     Move.w    #-2048,d2
  180.     Subq.w    #1,d0
  181.  
  182.     Cmp.w    #4096,d1
  183.     Bgt.s    .Enlarging
  184.  
  185. .Loop    Add.w    d1,d2
  186.     Blt.s    .GoLoop
  187.     Sub.w    #4096,d2
  188.     Move.b    (a0)+,(a1)+
  189.     Dbra    d0,.Loop
  190.     Bra.s    .Exit
  191. .GoLoop    Addq.l    #1,a0
  192.     Dbra    d0,.Loop
  193.     Bra.s    .Exit
  194.  
  195. .Enlarging    Add.w    d1,d2
  196. .Loop2    Move.b    (a0),(a1)+
  197.     Sub.w    #4096,d2
  198.     Bge.s    .Loop2
  199.     Addq.l    #1,a0
  200.     Dbra    d0,.Enlarging
  201.  
  202. .Exit    Movem.l    (sp)+,d0-d2/a0-a1
  203.     Rts
  204.  
  205.  
  206.  
  207.     CNOP    0,4
  208. _RGBTOFTC    ; IN: a0.l = Input (RGB buffer)
  209.     ; IN: a1.l = Output (FTC buffer)
  210.     ; IN: d0.w = Width in pixels
  211.     ; IN: d1.w = Height in pixels
  212.     ; IN: d2.w = Renderdepth
  213.  
  214.     Movem.l    a0-a2/d1-d2/d4-d7,-(sp)
  215.  
  216.     Move.w    d2,d4
  217.     Add.w    d4,d4
  218.     Add.w    d2,d4
  219.     Lea    FTCtable-3(pc,d4.w),a2
  220.     Move.b    (a2)+,d5
  221.     Move.b    (a2)+,d6
  222.     Move.b    (a2)+,d7
  223.  
  224.     Subq.w    #1,d1
  225.  
  226. .YLoop    Move.w    d0,d4
  227.     Subq.w    #1,d4
  228.  
  229. .XLoop    Moveq    #0,d2
  230.     Move.b    (a0)+,d2
  231.     Lsl.w    d5,d2
  232.     Move.b    (a0)+,d2
  233.     Lsl.w    d6,d2
  234.     Move.b    (a0)+,d2
  235.     Lsl.w    d7,d2
  236.     Lsr.w    #8,d2
  237.     Move.b    d2,(a1)+
  238.     Dbra    d4,.XLoop
  239.  
  240.     Dbra    d1,.YLoop
  241.  
  242.     Movem.l    (sp)+,a0-a2/d1-d2/d4-d7
  243.     Rts
  244.  
  245. FTCtable    Dc.b    0,1,0
  246.     Dc.b    1,1,0
  247.     Dc.b    1,1,1
  248.     Dc.b    1,2,1
  249.     Dc.b    2,2,1
  250.     Dc.b    2,2,2
  251.     Dc.b    2,3,2
  252.     Dc.b    3,3,2
  253.  
  254.     RsReset
  255. Size    Rs.w    1    0
  256. Cursize    Rs.w    1    2
  257. Clearcode    Rs.w    1    4
  258. Endcode    Rs.w    1    6
  259. Newcodes    Rs.w    1    8    not worth a register
  260. Topslot    Rs.w    1    10
  261. Slot    Rs.w    1    12
  262. Navailbytes    Rs.w    1    14
  263. Nbitsleft    Rs.w    1    16
  264. Shiftreg    Rs.w    1    18
  265. Suffix    Rs.l    1    20
  266. Prefix    Rs.l    1    24
  267. Stack    Rs.l    1    28
  268. Sp    Rs.l    1    32    stack current location
  269. Oc    Rs.w    1    36
  270. Fc    Rs.w    1    38
  271. Row    Rs.w    1    40
  272. Interlaced    Rs.b    1    42
  273.  
  274.  
  275.     CNOP    0,4
  276. _DECODEGIF    ; IN: a0.l = struct ScreenNode *
  277.     ; IN: a1.l = UBYTE *buffer
  278.     ; IN: d0.w = rows
  279.     ;OUT: d0.l = Error code or zero if everything went okay.
  280.  
  281.     Movem.l    d1-d7/a0-a6,-(sp)
  282.  
  283.     Move.l    sn_BytesPerRow(a0),d7
  284.     Mulu    d0,d7
  285.  
  286.     Moveq    #-lh_SIZEOF*8,d1
  287.     Move.w    sn_Data+Row(a0),d2
  288.  
  289.     Move.b    sn_Data+Interlaced(a0),d3
  290.     Beq.s    .LLoop
  291.  
  292.     ; 4 = NextStart = 2*4, step 8
  293.     ; 3 = NextStart = 2*2, step 8
  294.     ; 2 = NextStart = 2*1, step 4
  295.     ; 1 = NextStart = 2*0.5, step 2
  296.  
  297.     Cmp.b    #2,d3
  298.     Blt.s    .Type1
  299.     Beq.s    .Type2
  300.     Cmp.b    #3,d3
  301.     Beq.s    .Type3
  302.     Moveq    #8,d4
  303.     Moveq    #8,d5
  304.     Bra.s    .IntLoop
  305. .Type3    Moveq    #8,d4
  306.     Moveq    #4,d5
  307.     Bra.s    .IntLoop
  308. .Type2    Moveq    #4,d4
  309.     Moveq    #2,d5
  310.     Bra.s    .IntLoop
  311. .Type1    Moveq    #2,d4
  312.     Moveq    #1,d5
  313.  
  314. .IntLoop    Move.w    d2,lh_Row(a1,d1.w)
  315.     Add.w    d4,d2
  316.     Move.b    d5,lh_Repeatrow(a1,d1.w)
  317. .IntRetry    Cmp.w    sn_Height(a0),d2
  318.     Blt.s    .IntCont
  319.  
  320.     Subq.b    #1,sn_Data+Interlaced(a0)
  321.     Lsr.w    #1,d5    NextStart
  322.     Move.w    d5,d2
  323.     Cmp.w    #4,d5
  324.     Beq.s    .IntSkip
  325.     Lsr.w    #1,d4    Step
  326. .IntSkip    Bra.s    .IntRetry
  327.  
  328. .IntCont    Addq.w    #lh_SIZEOF,d1
  329.     Bne.s    .IntLoop
  330.  
  331.     Bra.s    .Continue
  332.  
  333.  
  334. .LLoop    Move.w    d2,lh_Row(a1,d1.w)
  335.     Addq.w    #1,d2
  336.     Move.b    #1,lh_Repeatrow(a1,d1.w)
  337.  
  338.     Addq.w    #lh_SIZEOF,d1
  339.     Bne.s    .LLoop
  340.  
  341.  
  342.  
  343. .Continue    Move.w    d2,sn_Data+Row(a0)
  344.  
  345.     Move.w    sn_Data+Nbitsleft(a0),d2
  346.     Move.w    sn_Data+Navailbytes(a0),d3
  347.     Move.w    sn_Data+Shiftreg(a0),d4
  348.     Move.w    sn_Data+Cursize(a0),d5
  349.     Move.w    sn_Data+Slot(a0),d6
  350.  
  351.     Move.l    sn_Data+Sp(a0),a2
  352.     Move.w    sn_Data+Fc(a0),a3
  353.     Move.w    sn_Data+Oc(a0),a4
  354.     Move.l    sn_Data+Suffix(a0),a5
  355.     Move.l    sn_Data+Prefix(a0),a6
  356.  
  357.  
  358.     ;Register layout:
  359.     ;d0.w = c
  360.     ;d1.w = code, or scratch for getnextcode!
  361.     ;d2.w = nbits_left
  362.     ;d3.w = navail_bytes
  363.     ;d4.w = b1 (shift-bit register) bits 8-15 must be clear always
  364.     ;d5.w = curr_size
  365.     ;d6.w = slot
  366.     ;d7.l = bufcnt
  367.  
  368.     ;a0.l = ScreenNode *
  369.     ;a1.l = UBYTE *buffer
  370.     ;a2.l = sp (stack pointer)
  371.     ;a3.w = fc
  372.     ;a4.w = oc
  373.     ;a5.l = suffix
  374.     ;a6.l = prefix
  375.  
  376. .DoWhile    Cmp.l    sn_Data+Stack(a0),a2
  377.     Ble.s    .Loop
  378.  
  379.     Move.b    -(a2),(a1)+
  380.     Subq.l    #1,d7
  381.     Bne.s    .DoWhile
  382.  
  383.     ; Save registers, loopinfo and stuff, then return
  384. .SaveRegs    Move.w    d2,sn_Data+Nbitsleft(a0)
  385.     Move.w    d3,sn_Data+Navailbytes(a0)
  386.     Move.w    d4,sn_Data+Shiftreg(a0)
  387.     Move.w    d5,sn_Data+Cursize(a0)
  388.     Move.w    d6,sn_Data+Slot(a0)
  389.  
  390.     Move.l    a2,sn_Data+Sp(a0)
  391.     Move.w    a3,sn_Data+Fc(a0)
  392.     Move.w    a4,sn_Data+Oc(a0)
  393.     Moveq    #0,d0
  394. .Exit    Movem.l    (sp)+,d1-d7/a0-a6
  395.     Rts
  396.  
  397.  
  398. .Loop    Bsr    GetNextCode
  399.     ;OUT: d0 = the next code
  400.     Cmp.w    sn_Data+Endcode(a0),d0
  401.     Beq.s    .EndOfGif
  402.  
  403.     Cmp.w    sn_Data+Clearcode(a0),d0
  404.     Bne.s    .NotClearCode
  405.  
  406.     Move.w    sn_Data+Size(a0),d5    cursize
  407.     Addq.w    #1,d5
  408.  
  409.     Moveq    #1,d6
  410.     Lsl.w    d5,d6
  411.     Move.w    d6,sn_Data+Topslot(a0)
  412.  
  413.     Move.w    sn_Data+Newcodes(a0),d6    slot
  414.  
  415. .AnotherClearCode    Bsr    GetNextCode
  416.     ;OUT: d0 = the next code
  417.     Cmp.w    sn_Data+Clearcode(a0),d0
  418.     Beq.s    .AnotherClearCode
  419.  
  420.     Cmp.w    sn_Data+Endcode(a0),d0
  421.     Bne.s    .NotEnding
  422. .EndOfGif    Moveq    #ERROR_END_OF_STREAM,d0
  423.     Bra.s    .Exit
  424.  
  425. .NotEnding    Cmp.w    d0,d6    Code,Slot
  426.     Bgt.s    .NotBeyondRange
  427.     Moveq    #0,d0
  428.  
  429. .NotBeyondRange    Move.w    d0,a3
  430.     Move.w    d0,a4
  431.  
  432.     Move.b    d0,(a1)+
  433.     Subq.l    #1,d7
  434.     Bne.s    .Loop
  435.  
  436.     Bra    .SaveRegs
  437.  
  438.  
  439.  
  440. .NotClearCode    Move.w    d0,d1
  441.     Cmp.w    d1,d6    code,slot
  442.     Bgt.s    .CodeIsInRange
  443.     ;Beq.s    .NotABadCode
  444.     ;Encountered a bad code... what should we do with it?
  445.     ;The example code simply increased a counter and ignored it.
  446. .NotABadCode    Move.w    a4,d1
  447.     Exg    a3,d0
  448.     Move.b    d0,(a2)+
  449.     Exg    a3,d0
  450.  
  451. .CodeIsInRange    Cmp.w    sn_Data+Newcodes(a0),d1
  452.     Blt.s    .EndWhile
  453.  
  454.     Move.b    (a5,d1.w),(a2)+    suffix,stack
  455.     Move.w    (a6,d1.w*2),d1    prefix,code
  456.     Bra.s    .CodeIsInRange
  457.  
  458. .EndWhile    Move.b    d1,(a2)+
  459.     Cmp.w    sn_Data+Topslot(a0),d6
  460.     Bge.s    .Endif1
  461.     Move.b    d1,(a5,d6.w)
  462.     Move.w    d1,a3
  463.     Move.w    a4,(a6,d6.w*2)
  464.     Addq.w    #1,d6
  465.     Move.w    d0,a4
  466.  
  467. .Endif1    Cmp.w    sn_Data+Topslot(a0),d6
  468.     Blt.s    .Endif2
  469.     Cmp.w    #12,d5
  470.     Bge.s    .Endif2
  471.     Lsl.w    sn_Data+Topslot(a0)
  472.     Addq.w    #1,d5
  473.  
  474. .Endif2    Bra    .DoWhile
  475.  
  476.  
  477.  
  478.  
  479.  
  480.     CNOP    0,4
  481. GetNextCode    ; IN: d1.l = SCRATCH
  482.     ; IN: d2.w = nbits_left
  483.     ; IN: d3.w = navail_bytes
  484.     ; IN: d4.w = shift-bit register
  485.     ; IN: d5.w = curr_size
  486.     ; IN: a2.l = UBYTE *fileptr
  487.     ;OUT: d0.w = the next code
  488.     ; This routine gets next code which is d5 (curr_size) bits in size and
  489.     ; returns this x bit code in the lower bits of d0.  This routine can
  490.     ; never fail since the buffer is pre-read, and so I/O errors are not
  491.     ; of our concern.
  492.  
  493.     Move.l    a2,-(sp)
  494.     Move.l    sn_FilePtr(a0),a2
  495.  
  496.     Tst.w    d2
  497.     Bne.s    .NBitsLeftNotZero
  498.  
  499.     Tst.w    d3
  500.     Bgt.s    .NAvailBytesPos
  501.  
  502.     ; No more bytes in current block, so read the next block-counter
  503.     Moveq    #0,d3
  504.     Move.b    (a2)+,d3
  505.  
  506. .NAvailBytesPos    ; There were still bytes left in the current GIF block
  507.     Move.b    (a2)+,d4
  508.     Moveq    #8,d2
  509.     Subq.w    #1,d3
  510.  
  511. .NBitsLeftNotZero    Moveq    #8,d1
  512.     Sub.w    d2,d1
  513.     Move.w    d4,d0
  514.     Lsr.w    d1,d0
  515.  
  516. .While    Cmp.w    d5,d2
  517.     Bge.s    .EndWhile
  518.  
  519.     Tst.w    d3
  520.     Bgt.s    .NAvailBytesPos2
  521.  
  522.     ; No more bytes in current block, so read the next block-counter
  523.     Moveq    #0,d3
  524.     Move.b    (a2)+,d3
  525.  
  526. .NAvailBytesPos2    Move.b    (a2)+,d4
  527.  
  528.     Move.w    d4,d1
  529.     Lsl.w    d2,d1
  530.     Or.w    d1,d0
  531.  
  532.     Addq.w    #8,d2
  533.     Subq.w    #1,d3
  534.  
  535.     Bra.s    .While
  536.  
  537. .EndWhile    Sub.w    d5,d2
  538.     And.w    CodeMask(pc,d5.w*2),d0
  539.  
  540.     Move.l    a2,sn_FilePtr(a0)
  541.     Move.l    (sp)+,a2
  542.     Rts
  543.  
  544. CodeMask    Dc.w    0,1,3,7,15,31,63,127,255,511,1023,2047,4095
  545.  
  546.  
  547.     END
  548.  
  549.  
  550. /* DECODE.C - An LZW decoder for GIF
  551.  * Copyright (C) 1987, by Steven A. Bennett
  552.  *
  553.  * Permission is given by the author to freely redistribute and include
  554.  * this code in any program as long as this credit is given where due.
  555.  *
  556.  * In accordance with the above, I want to credit Steve Wilhite who wrote
  557.  * the code which this is heavily inspired by...
  558.  *
  559.  * GIF and 'Graphics Interchange Format' are trademarks (tm) of
  560.  * Compuserve, Incorporated, an H&R Block Company.
  561.  *
  562.  * Release Notes: This file contains a decoder routine for GIF images
  563.  * which is similar, structurally, to the original routine by Steve Wilhite.
  564.  * It is, however, somewhat noticably faster in most cases.
  565.  *
  566.  */
  567.  
  568. #include "std.h"
  569. #include "errs.h"
  570.  
  571. IMPORT TEXT *malloc();                 /* Standard C library allocation */
  572.  
  573. /* IMPORT INT get_byte()
  574.  *
  575.  *   - This external (machine specific) function is expected to return
  576.  * either the next byte from the GIF file, or a negative number, as
  577.  * defined in ERRS.H.
  578.  */
  579. IMPORT INT get_byte();
  580.  
  581. /* IMPORT INT out_line(pixels, linelen)
  582.  *     UBYTE pixels[];
  583.  *     INT linelen;
  584.  *
  585.  *   - This function takes a full line of pixels (one byte per pixel) and
  586.  * displays them (or does whatever your program wants with them...).  It
  587.  * should return zero, or negative if an error or some other event occurs
  588.  * which would require aborting the decode process...  Note that the length
  589.  * passed will almost always be equal to the line length passed to the
  590.  * decoder function, with the sole exception occurring when an ending code
  591.  * occurs in an odd place in the GIF file...  In any case, linelen will be
  592.  * equal to the number of pixels passed...
  593.  */
  594. IMPORT INT out_line();
  595.  
  596. /* IMPORT INT bad_code_count;
  597.  *
  598.  * This value is the only other global required by the using program, and
  599.  * is incremented each time an out of range code is read by the decoder.
  600.  * When this value is non-zero after a decode, your GIF file is probably
  601.  * corrupt in some way...
  602.  */
  603. IMPORT INT bad_code_count;
  604.  
  605. #define NULL   0L
  606. #define MAX_CODES   4095
  607.  
  608. /* Static variables */
  609. LOCAL WORD curr_size;                     /* The current code size */
  610. LOCAL WORD clear;                         /* Value for a clear code */
  611. LOCAL WORD ending;                        /* Value for a ending code */
  612. LOCAL WORD newcodes;                      /* First available code */
  613. LOCAL WORD top_slot;                      /* Highest code for current size */
  614. LOCAL WORD slot;                          /* Last read code */
  615.  
  616. /* The following static variables are used
  617.  * for seperating out codes
  618.  */
  619. LOCAL WORD navail_bytes = 0;              /* # bytes left in block */
  620. LOCAL WORD nbits_left = 0;                /* # bits left in current byte */
  621. LOCAL UTINY b1;                           /* Current byte */
  622. LOCAL UTINY byte_buff[257];               /* Current block */
  623. LOCAL UTINY *pbytes;                      /* Pointer to next byte in block */
  624.  
  625. LOCAL LONG code_mask[13] = {
  626.      0,
  627.      0x0001, 0x0003,
  628.      0x0007, 0x000F,
  629.      0x001F, 0x003F,
  630.      0x007F, 0x00FF,
  631.      0x01FF, 0x03FF,
  632.      0x07FF, 0x0FFF
  633.      };
  634.  
  635.  
  636. /* This function initializes the decoder for reading a new image.
  637.  */
  638. LOCAL WORD init_exp(WORD size) {
  639.    curr_size = size + 1;
  640.    top_slot = 1 << curr_size;
  641.    clear = 1 << size;
  642.    ending = clear + 1;
  643.    slot = newcodes = ending + 1;
  644.    navail_bytes = nbits_left = 0;
  645.    return(0);
  646. }
  647.  
  648. /* get_next_code()
  649.  * - gets the next code from the GIF file.  Returns the code, or else
  650.  * a negative number in case of file errors...
  651.  */
  652. LOCAL WORD get_next_code() {
  653.    WORD i, x;
  654.    ULONG ret;
  655.  
  656.    if (nbits_left == 0) {
  657.       if (navail_bytes <= 0) {
  658.  
  659.          /* Out of bytes in current block, so read next block
  660.           */
  661.          pbytes = byte_buff;
  662.          if ((navail_bytes = get_byte()) < 0)
  663.             return(navail_bytes);
  664.          else if (navail_bytes) {
  665.             for (i = 0; i < navail_bytes; ++i) {
  666.                if ((x = get_byte()) < 0)
  667.                   return(x);
  668.                byte_buff[i] = x;
  669.             }
  670.          }
  671.       }
  672.  
  673.       b1 = *pbytes++;
  674.       nbits_left = 8;
  675.       --navail_bytes;
  676.    }
  677.  
  678.    ret = b1 >> (8 - nbits_left);
  679.    while (curr_size > nbits_left) {
  680.       if (navail_bytes <= 0) {
  681.  
  682.          /* Out of bytes in current block, so read next block
  683.           */
  684.          pbytes = byte_buff;
  685.          if ((navail_bytes = get_byte()) < 0)
  686.             return(navail_bytes);
  687.          else if (navail_bytes) {
  688.             for (i = 0; i < navail_bytes; ++i) {
  689.                if ((x = get_byte()) < 0)
  690.                   return(x);
  691.                byte_buff[i] = x;
  692.             }
  693.          }
  694.       }
  695.       b1 = *pbytes++;
  696.       ret |= b1 << nbits_left;
  697.       nbits_left += 8;
  698.       --navail_bytes;
  699.    }
  700.    nbits_left -= curr_size;
  701.    ret &= code_mask[curr_size];
  702.    return((WORD)(ret));
  703. }
  704.  
  705.  
  706. /* The reason we have these seperated like this instead of using
  707.  * a structure like the original Wilhite code did, is because this
  708.  * stuff generally produces significantly faster code when compiled...
  709.  * This code is full of similar speedups...  (For a good book on writing
  710.  * C for speed or for space optomisation, see Efficient C by Tom Plum,
  711.  * published by Plum-Hall Associates...)
  712.  */
  713. LOCAL UTINY stack[MAX_CODES + 1];            /* Stack for storing pixels */
  714. LOCAL UTINY suffix[MAX_CODES + 1];           /* Suffix table */
  715. LOCAL UWORD prefix[MAX_CODES + 1];           /* Prefix linked list */
  716.  
  717. /* WORD decoder(linewidth)
  718.  *    WORD linewidth;               * Pixels per line of image *
  719.  *
  720.  * - This function decodes an LZW image, according to the method used
  721.  * in the GIF spec.  Every *linewidth* "characters" (ie. pixels) decoded
  722.  * will generate a call to out_line(), which is a user specific function
  723.  * to display a line of pixels.  The function gets it's codes from
  724.  * get_next_code() which is responsible for reading blocks of data and
  725.  * seperating them into the proper size codes.  Finally, get_byte() is
  726.  * the global routine to read the next byte from the GIF file.
  727.  *
  728.  * It is generally a good idea to have linewidth correspond to the actual
  729.  * width of a line (as specified in the Image header) to make your own
  730.  * code a bit simpler, but it isn't absolutely necessary.
  731.  *
  732.  * Returns: 0 if successful, else negative.  (See ERRS.H)
  733.  *
  734.  */
  735.  
  736. WORD decoder(WORD linewidth) {
  737.    FAST UTINY *sp, *bufptr;
  738.    UTINY *buf;
  739.    FAST WORD code, fc, oc, bufcnt;
  740.    WORD c, size, ret;
  741.  
  742.    /* Initialize for decoding a new image...
  743.     */
  744.    if ((size = get_byte()) < 0)
  745.       return(size);
  746.    if (size < 2 || 9 < size)
  747.       return(BAD_CODE_SIZE);
  748.    init_exp(size);
  749.  
  750.    /* Initialize in case they forgot to put in a clear code.
  751.     * (This shouldn't happen, but we'll try and decode it anyway...)
  752.     */
  753.    oc = fc = 0;
  754.  
  755.    /* Allocate space for the decode buffer
  756.     */
  757.    if ((buf = (UTINY *)malloc(linewidth + 1)) == NULL)
  758.       return(OUT_OF_MEMORY);
  759.  
  760.    /* Set up the stack pointer and decode buffer pointer
  761.     */
  762.    sp = stack;
  763.    bufptr = buf;
  764.    bufcnt = linewidth;
  765.  
  766.    /* This is the main loop.  For each code we get we pass through the
  767.     * linked list of prefix codes, pushing the corresponding "character" for
  768.     * each code onto the stack.  When the list reaches a single "character"
  769.     * we push that on the stack too, and then start unstacking each
  770.     * character for output in the correct order.  Special handling is
  771.     * included for the clear code, and the whole thing ends when we get
  772.     * an ending code.
  773.     */
  774.    while ((c = get_next_code()) != ending) {
  775.  
  776.       /* If we had a file error, return without completing the decode
  777.        */
  778.       if (c < 0)
  779.          {
  780.          free(buf);
  781.          return(0);
  782.          }
  783.  
  784.       /* If the code is a clear code, reinitialize all necessary items.
  785.        */
  786.       if (c == clear) {
  787.          curr_size = size + 1;
  788.          slot = newcodes;
  789.          top_slot = 1 << curr_size;
  790.  
  791.          /* Continue reading codes until we get a non-clear code
  792.           * (Another unlikely, but possible case...)
  793.           */
  794.          while ((c = get_next_code()) == clear)
  795.             ;
  796.  
  797.          /* If we get an ending code immediately after a clear code
  798.           * (Yet another unlikely case), then break out of the loop.
  799.           */
  800.          if (c == ending)
  801.             break;
  802.  
  803.          /* Finally, if the code is beyond the range of already set codes,
  804.           * (This one had better NOT happen...  I have no idea what will
  805.           * result from this, but I doubt it will look good...) then set it
  806.           * to color zero.
  807.           */
  808.          if (c >= slot)
  809.             c = 0;
  810.  
  811.          oc = fc = c;
  812.  
  813.          /* And let us not forget to put the char into the buffer... And
  814.           * if, on the off chance, we were exactly one pixel from the end
  815.           * of the line, we have to send the buffer to the out_line()
  816.           * routine...
  817.           */
  818.          *bufptr++ = c;
  819.          if (--bufcnt == 0) {
  820.             if ((ret = out_line(buf, linewidth)) < 0) {
  821.                free(buf);
  822.                return(ret);
  823.             }
  824.             bufptr = buf;
  825.             bufcnt = linewidth;
  826.          }
  827.       }
  828.       else {
  829.  
  830.          /* In this case, it's not a clear code or an ending code, so
  831.           * it must be a code code...  So we can now decode the code into
  832.           * a stack of character codes. (Clear as mud, right?)
  833.           */
  834.          code = c;
  835.  
  836.          /* Here we go again with one of those off chances...  If, on the
  837.           * off chance, the code we got is beyond the range of those already
  838.           * set up (Another thing which had better NOT happen...) we trick
  839.           * the decoder into thinking it actually got the last code read.
  840.           * (Hmmn... I'm not sure why this works...  But it does...)
  841.           */
  842.          if (code >= slot) {
  843.             if (code > slot)
  844.                ++bad_code_count;
  845.             code = oc;
  846.             *sp++ = fc;
  847.          }
  848.  
  849.          /* Here we scan back along the linked list of prefixes, pushing
  850.           * helpless characters (ie. suffixes) onto the stack as we do so.
  851.           */
  852.          while (code >= newcodes) {
  853.             *sp++ = suffix[code];   // bytes
  854.             code = prefix[code];    // words
  855.          }
  856.  
  857.          /* Push the last character on the stack, and set up the new
  858.           * prefix and suffix, and if the required slot number is greater
  859.           * than that allowed by the current bit size, increase the bit
  860.           * size.  (NOTE - If we are all full, we *don't* save the new
  861.           * suffix and prefix...  I'm not certain if this is correct...
  862.           * it might be more proper to overwrite the last code...
  863.           */
  864.          *sp++ = code;
  865.          if (slot < top_slot) {
  866.             suffix[slot] = fc = code;
  867.             prefix[slot++] = oc;
  868.             oc = c;
  869.          }
  870.          if (slot >= top_slot) {
  871.             if (curr_size < 12) {
  872.                top_slot <<= 1;
  873.                ++curr_size;
  874.             }
  875.          }
  876.  
  877.          /* Now that we've pushed the decoded string (in reverse order)
  878.           * onto the stack, lets pop it off and put it into our decode
  879.           * buffer...  And when the decode buffer is full, write another
  880.           * line...
  881.           */
  882.          while (sp > stack) {
  883.             *bufptr++ = *(--sp);
  884.             if (--bufcnt == 0) {
  885.                if ((ret = out_line(buf, linewidth)) < 0) {
  886.                   free(buf);
  887.                   return(ret);
  888.                }
  889.                bufptr = buf;
  890.                bufcnt = linewidth;
  891.             }
  892.          }
  893.       }
  894.    }
  895.    ret = 0;
  896.    if (bufcnt != linewidth)
  897.       ret = out_line(buf, (linewidth - bufcnt));
  898.    free(buf);
  899.    return(ret);
  900.    }
  901.  
  902.  
  903.  
  904.  
  905.     END
  906.  
  907. ERROR_WHILE_DECODING = 25
  908.  
  909. MC68000    EQU    0
  910.  
  911.     Opt    l+
  912.  
  913.     XDef    _DECODEJPEG
  914.  
  915.     Incdir    "INCLUDE:"
  916.  
  917.     Include    "exec/nodes.i"
  918.     Include    "exec/types.i"
  919.  
  920.     Include    "WORK:GifRtnFV.s"
  921.  
  922.  STRUCTURE ScreenNode,0
  923.   STRUCT sn_node,LN_SIZE
  924.  
  925.   STRUCT sn_data,16 ; private to the XXX functions
  926.   UWORD sn_width    ; these describe the picture on disk
  927.   UWORD sn_height
  928.   UWORD sn_depth    ; 2^depth is not necessarily the number of colors (HAM)
  929.   UWORD sn_colors   ; not initid if truecolor = TRUE
  930.   UWORD sn_aspectx
  931.   UWORD sn_aspecty
  932.  
  933.   ; following UBYTE's are TRUE or FALSE
  934.   UBYTE sn_truecolor  ; No palette-info depth 1-8 = gray   depth 15,16,24 = color
  935.   UBYTE sn_ham        ; depth 6 = HAM6   depth 8 = HAM8
  936.   UBYTE sn_ehb
  937.   UBYTE sn_planar
  938.  
  939.   ; now follows space for a 256-color palette (4 bytes/entry)
  940.   STRUCT sn_palette,1024
  941.  
  942.   ; following UBYTE's are TRUE or FALSE and are set by the BestModeID function
  943.   ; to help the rendering routines
  944.   UBYTE sn_rerender
  945.   UBYTE sn_gray
  946.   UBYTE sn_deep       ; not set means HAM6/GRAY4, set means HAM8/GRAY8
  947.   UBYTE sn_halvewidth
  948.   UBYTE sn_direct     ; direct HAM or EHB, if TRUE then rerender must be FALSE
  949.  
  950.   UBYTE sn_pad
  951.   WORD  sn_renderaspect
  952.   ULONG sn_displayid
  953.   UWORD sn_nominalw
  954.   UWORD sn_nominalh
  955.  
  956.   ; following fields are not to be modified by the initXXX or exitXXX routines
  957.   ULONG sn_lock       ; lock on the dir this file is located in
  958.   APTR  sn_screen
  959.   APTR  sn_window
  960.   ULONG sn_buffer
  961.  
  962.   UWORD sn_renderw
  963.   UWORD sn_renderh
  964.   UWORD sn_renderd
  965.   UWORD sn_pad2
  966.  
  967.   ULONG sn_buffersmemory
  968.  
  969.   ULONG sn_linebuffer
  970.   ULONG sn_rgbbuffer
  971.   ULONG sn_bytebuffer
  972.  
  973.   ULONG sn_floydbuf1
  974.   ULONG sn_floydbuf2
  975.  
  976.   UWORD sn_outputline
  977.  
  978.     CNOP    0,4
  979. _DECODEJPEG    ; IN: a0.l = struct ScreenNode *
  980.     ;OUT: d0.l = Error code, zero if okay
  981.     Movem.l    d1-d7/a0-a5,-(sp)
  982.  
  983.     Move.l    a0,a5
  984. .YLoop    ;SingleLine
  985.     Moveq    #0,d2
  986.     Move.w    sn_width(a5),d2
  987. ;    Cmp.w    #1,d7
  988. ;    Beq.s    .Gray
  989.     Add.w    d2,d2
  990.     Add.w    sn_width(a5),d2
  991. ;.Gray
  992.     Move.l    d2,-(sp)    Bufsize
  993.     Move.l    sn_rgbbuffer(a5),-(sp)    Buffer
  994.     Move.l    #$73202,-(sp)    CDM_PROCESS
  995.     Move.l    sn_data(a5),-(sp)    Object
  996.     Bsr    DoMethod
  997.     Lea    16(sp),sp
  998.  
  999.     Cmp.l    d0,d2
  1000.     Bne.s    .Error
  1001.  
  1002.     Bsr    ProcessLine
  1003.     ;Bsr    CheckMouse
  1004.     ;Bne.s    .UserExited
  1005.  
  1006.     Dbra    d6,.YLoop
  1007.  
  1008.     Moveq    #0,d0
  1009. .Exit    Movem.l    (sp)+,d1-d7/a0-a5
  1010.     Rts
  1011. .Error    Moveq    #ERROR_WHILE_DECODING,d0
  1012.     Bra.s    .Exit
  1013.  
  1014.  
  1015.  
  1016.     CNOP    0,4
  1017. DoMethod    Move.l    A2,-(SP)
  1018.     Movea.l    $8(SP),A2
  1019.     Move.l    A2,D0
  1020.     Beq.s    LabA9A
  1021.     Lea    $C(SP),A1
  1022.     Movea.l    -$4(A2),A0
  1023.     Bra.s    LabA90
  1024.  
  1025.     Move.l    A2,-(SP)
  1026.     Movem.l    $8(SP),A0/A2
  1027.     Move.l    A2,D0
  1028.     Beq.s    LabA9A
  1029.     Move.l    A0,D0
  1030.     Beq.s    LabA9A
  1031.     Lea    $10(SP),A1
  1032.     Movea.l    $18(A0),A0
  1033.     Bra.s    LabA90
  1034.  
  1035.     Move.l    A2,-(SP)
  1036.     Movem.l    $8(SP),A0/A2
  1037.     Move.l    A2,D0
  1038.     Beq.s    LabA9A
  1039.     Move.l    A0,D0
  1040.     Beq.s    LabA9A
  1041.     Lea    $10(SP),A1
  1042.     Bra.s    LabA90
  1043.  
  1044.     Move.l    A2,-(SP)
  1045.     Movem.l    $8(SP),A0/A2
  1046.     Move.l    A2,D0
  1047.     Beq.s    LabA9A
  1048.     Move.l    A0,D0
  1049.     Beq.s    LabA9A
  1050.     Movea.l    $10(SP),A1
  1051. LabA90    Pea    LabA9C
  1052.     Move.l    $8(A0),-(SP)
  1053.     Rts
  1054.  
  1055. LabA9A    Moveq    #$0,D0
  1056. LabA9C    Movea.l    (SP)+,A2
  1057.  
  1058.     Rts
  1059.  
  1060.  
  1061.  
  1062.     CNOP    0,4
  1063. ProcessLine    ; IN: a5.l = struct ScreenNode *
  1064.     Movem.l    d0-d7/a0-a6,-(sp)
  1065.  
  1066.     Tst.b    sn_halvewidth(a5)
  1067.     Beq.s    .HAM.NoHalve
  1068.     Move.l    sn_rgbbuffer(a5),a0
  1069.     Move.w    sn_width(a5),d0
  1070.     Bsr    HalveRGB
  1071.  
  1072. .HAM.NoHalve    Move.l    sn_rgbbuffer(a5),a0
  1073.     Move.l    sn_bytebuffer(a5),a1
  1074.     Lea    HamPalette(pc),a2
  1075.     Lea    CacheMem(pc),a3
  1076.     Move.w    sn_width(a5),d0
  1077.     ; IN: a0.l = Ptr to RGB line (3 words/color)
  1078.     ; IN: a1.l = Ptr to HAM output buffer
  1079.     ; IN: a2.l = Ptr to HAM-palette (4 words/color)
  1080.     ; IN: a3.l = Ptr to 32768 bytes of cache memory
  1081.     ; IN: d0.w = Length of RGB in pixels
  1082.     Bsr    RGBtoHAM
  1083.  
  1084.     Move.l    sn_bytebuffer(a5),a0
  1085.     Move.w    sn_outputline(a5),d1
  1086.     Addq.w    #1,sn_outputline(a5)
  1087.     Bsr    ChunkyToPlanar    destroys -all- registers
  1088.  
  1089.     Movem.l    (sp)+,d0-d7/a0-a6
  1090.     Rts
  1091.  
  1092.  
  1093. HamPalette    Dc.w    0,$00,$00,$00
  1094.     Dc.w    0,$11,$11,$11
  1095.     Dc.w    0,$22,$22,$22
  1096.     Dc.w    0,$33,$33,$33
  1097.     Dc.w    0,$44,$44,$44
  1098.     Dc.w    0,$55,$55,$55
  1099.     Dc.w    0,$66,$66,$66
  1100.     Dc.w    0,$77,$77,$77
  1101.     Dc.w    0,$88,$88,$88
  1102.     Dc.w    0,$99,$99,$99
  1103.     Dc.w    0,$aa,$aa,$aa
  1104.     Dc.w    0,$bb,$bb,$bb
  1105.     Dc.w    0,$cc,$cc,$cc
  1106.     Dc.w    0,$dd,$dd,$dd
  1107.     Dc.w    0,$ee,$ee,$ee
  1108.     Dc.w    0,$ff,$ff,$ff
  1109.  
  1110. CacheMem    Ds.b    4096
  1111.  
  1112.     END
  1113.  
  1114.  
  1115.  
  1116.  
  1117.     output the line
  1118.     Tst.l    Cat(a5)
  1119.     Beq.s    .Cont
  1120.     Bra    OutputLineRtnCat
  1121.  
  1122. .Cont    Movem.l    d0-d7/a0-a6,-(sp)
  1123.  
  1124.     Tst.l    Scale(a5)
  1125.     Beq.s    .NoScale
  1126.  
  1127.     Move.w    ScaleLevel(a5),d0
  1128.     Add.w    d0,VerScale(a5)
  1129.     Blt    .Exit
  1130.     Sub.w    #64,VerScale(a5)
  1131.  
  1132. .NoScale    Tst.b    sn_planar(a4)    Planar or Chunky?
  1133.     Beq    .Chunky
  1134.  
  1135.     Move.w    sn_width(a4),d0
  1136.     Move.l    sn_linebuffer(a4),a2
  1137.     Cmp.w    #24,sn_depth(a4)
  1138.     Bne.s    .Normal
  1139.     Moveq    #1,d3
  1140.     Move.l    sn_rgbbuffer(a4),a0
  1141.     Bsr    PlanarToChunky
  1142.     Move.w    sn_width(a4),d0
  1143.     Add.w    #15,d0
  1144.     And.w    #-16,d0
  1145.     Add.w    d0,a2
  1146.     Move.w    sn_width(a4),d0
  1147.     Addq.l    #1,a0
  1148.     Bsr    PlanarToChunky
  1149.     Move.w    sn_width(a4),d0
  1150.     Add.w    #15,d0
  1151.     And.w    #-16,d0
  1152.     Add.w    d0,a2
  1153.     Move.w    sn_width(a4),d0
  1154.     Addq.l    #1,a0
  1155.     Bsr    PlanarToChunky
  1156.     Bra.s    .Chunky
  1157.  
  1158. .Normal    Move.l    sn_bytebuffer(a4),a0
  1159.     Moveq    #0,d3
  1160.     Bsr    PlanarToChunky
  1161.  
  1162.     Tst.b    sn_ham(a4)
  1163.     Beq.s    .Chunky
  1164.     Tst.b    sn_rerender(a4)
  1165.     Beq.s    .Chunky
  1166.     Tst.b    sn_gray(a4)
  1167.     Bne.s    .Chunky
  1168.     Cmp.w    #8,sn_depth(a4)
  1169.     Bne.s    .Chunky
  1170.  
  1171.     Move.w    sn_width(a4),d0
  1172.     Move.l    a0,a2
  1173.     Move.l    sn_rgbbuffer(a4),a0
  1174.     Lea    sn_palette(a4),a1
  1175.     Bsr    HAM8ToRGB
  1176.  
  1177. .Chunky    Tst.b    sn_rerender(a4)
  1178.     Beq.s    .Direct
  1179.     Tst.b    sn_gray(a4)
  1180.     Bne.s    .Gray
  1181.     Bra    .HAM
  1182.  
  1183. .Direct    Move.l    sn_bytebuffer(a4),a0
  1184.     Tst.b    sn_truecolor(a4)
  1185.     Beq.s    .NotGray
  1186.     Cmp.w    #8,sn_depth(a4)
  1187.     Bgt.s    .NotGray
  1188.     Move.l    sn_rgbbuffer(a4),a0
  1189. .NotGray
  1190.     Tst.l    Scale(a5)
  1191.     Beq.s    .Direct.NoScale
  1192.     Move.w    sn_RenderW(a4),d1
  1193.     Bsr    PaletteScalerSimple    preserves A0
  1194. .Direct.NoScale    Move.l    a0,a1
  1195.     Bra    .Render8bit
  1196.  
  1197. .Gray    Btst    #0,DataInput(a5)    24 bit or 8 bit?
  1198.     Beq.s    .Gray.8bit
  1199.     Move.l    RGBBuffer(a5),a0
  1200.     Move.w    sn_W(a4),d0
  1201.     Bsr    RGBtoGray
  1202.     Bra.s    .Gray.Render
  1203.  
  1204. .Gray.8bit    Btst    #1,DataInput(a5)
  1205.     Bne.s    .Gray.Render
  1206.     Move.l    RGBBuffer(a5),a0
  1207.     Lea    sn_Palette(a4),a1
  1208.     Move.l    ByteBuffer(a5),a2
  1209.     Move.w    sn_W(a4),d0
  1210.     Bsr    PaletteToGray
  1211.  
  1212. .Gray.Render    Tst.l    Scale(a5)
  1213.     Beq.s    .Gray.NoScale
  1214.  
  1215.     Move.l    RGBBuffer(a5),a0
  1216.     Move.w    sn_RenderW(a4),d1
  1217.     Bsr    GrayScalerSimple
  1218.  
  1219. .Gray.NoScale    Move.l    RGBBuffer(a5),a0
  1220.     Move.l    ByteBuffer(a5),a1
  1221.     Move.w    sn_W(a4),d0
  1222.     Moveq    #8,d1
  1223.     Sub.w    sn_RenderDepth(a4),d1
  1224.     Tst.l    Dither(a5)
  1225.     Bne.s    .Gray.Dither
  1226.     Bsr    RGBtoBW    d0-d1 destroyed
  1227.     Bra    .Render8bit
  1228. .Gray.Dither    Bsr    RGBtoBWdither    d0-d2 destroyed
  1229.     Bra    .Render8bit
  1230.  
  1231.  
  1232. .HAM    Btst    #0,DataInput(a5)    24 bit or 8 bit?
  1233.     Bne.s    .HAM.24bit
  1234.  
  1235.     Move.l    RGBBuffer(a5),a0
  1236.     Lea    sn_Palette(a4),a1
  1237.     Move.l    ByteBuffer(a5),a2
  1238.     Move.w    sn_W(a4),d0
  1239.     Bsr    PaletteToRGB    d0-d4 destroyed
  1240.     Bra.s    .HAM.NoHalve
  1241.  
  1242. .HAM.24bit    Tst.b    HalveWidth(a5)
  1243.     Beq.s    .HAM.NoHalve
  1244.     Move.l    RGBBuffer(a5),a0
  1245.     Move.w    sn_W(a4),d0
  1246.     Bsr    HalveRGB
  1247.  
  1248. .HAM.NoHalve    Tst.l    MakeComment(a5)
  1249.     Beq.s    .HAM.NoHistogram
  1250.     Tst.b    HistogramAvailable(a5)
  1251.     Bne.s    .HAM.NoHistogram
  1252.  
  1253.     Move.l    RGBBuffer(a5),a2
  1254.     Move.l    a5,a1
  1255.     Add.l    #Histogram,a1
  1256.     Move.w    sn_W(a4),d0
  1257.     Tst.b    HalveWidth(a5)
  1258.     Beq.s    .HAM.NoHalve2
  1259.     Addq.w    #1,d0
  1260.     Lsr.w    #1,d0
  1261. .HAM.NoHalve2    Subq.w    #1,d0
  1262. .HAM.Loop    Move.b    (a2)+,d3
  1263.     Lsl.w    #4,d3
  1264.     Move.b    (a2)+,d3
  1265.     Lsl.w    #4,d3
  1266.     Move.b    (a2)+,d3
  1267.     Lsr.w    #4,d3
  1268.  
  1269.     IFNE    MC68000
  1270.     Add.w    d3,d3
  1271.     Move.w    (a1,d3.w),d2
  1272.     ELSE
  1273.     Move.w    (a1,d3.w*2),d2
  1274.     ENDC
  1275.     Cmp.w    #65530,d2
  1276.     Bhi.s    .HAM.NoInc
  1277.     Addq.w    #1,d2
  1278.     IFNE    MC68000
  1279.     Move.w    d2,(a1,d3.w)
  1280.     ELSE
  1281.     Move.w    d2,(a1,d3.w*2)
  1282.     ENDC
  1283.  
  1284.     IFNE    MC68000
  1285.     Add.w    d3,d3
  1286.     Addq.w    #1,(a1,d3.w)
  1287.     ELSE
  1288.     Addq.w    #1,(a1,d3.w*2)
  1289.     ENDC
  1290.     Bcc.s    .HAM.NoInc
  1291.     IFNE    MC68000
  1292.     Move.w    #65530,(a1,d3.w)
  1293.     ELSE
  1294.     Move.w    #65530,(a1,d3.w*2)
  1295.     ENDC
  1296. .HAM.NoInc    Dbra    d0,.HAM.Loop
  1297.  
  1298. .HAM.NoHistogram    Tst.l    Scale(a5)
  1299.     Beq.s    .HAM.NoScale
  1300.  
  1301.     Move.l    RGBBuffer(a5),a0
  1302.     Move.w    sn_RenderW(a4),d1
  1303.     Bsr    RGBScalerSimple
  1304.  
  1305. .HAM.NoScale    Move.w    sn_RenderW(a4),d0
  1306.     Move.l    RGBBuffer(a5),a0
  1307.     Move.l    ByteBuffer(a5),a1
  1308.     Lea    sn_RenderPalette(a4),a2
  1309.     Move.l    a5,a3
  1310.     Add.l    #Cache,a3
  1311.  
  1312.     Tst.l    Dither(a5)
  1313.     Bne.s    .HAM.Dither
  1314.     Cmp.b    #3,Render+1(a5)
  1315.     Beq.s    .HAM8.NoDither
  1316.     Bsr    RGBtoHAM    d0-d7 destroyed
  1317.     Bra.s    .Render8bit
  1318. .HAM8.NoDither    Bsr    RGBtoHAM8    d0-d7 destroyed
  1319.     Bra.s    .Render8bit
  1320. .HAM.Dither    Cmp.b    #3,Render+1(a5)
  1321.     Beq.s    .HAM8.Dither
  1322.     Bsr    RGBtoHAMdither    d0-d7 destroyed
  1323.     Bra.s    .Render8bit
  1324. .HAM8.Dither    Bsr    RGBtoHAM8dither    d0-d7 destroyed
  1325.     Bra    .Render8bit
  1326.  
  1327. .Render8bit    ; IN: a1.l = Ptr to 8-bit buffer
  1328.     Move.l    a1,a0
  1329. .NotByteBuffer    Move.l    sn_Screen(a4),d0
  1330.     Bne.s    .RenderToScreen
  1331.     Move.l    sn_BufferCurrent(a4),a1
  1332.     Move.w    sn_RoundW(a4),d0
  1333.     Lsr.w    #4,d0
  1334.     Subq.w    #1,d0
  1335. .CopyToBuffer    Move.l    (a0)+,(a1)+
  1336.     Move.l    (a0)+,(a1)+
  1337.     Move.l    (a0)+,(a1)+
  1338.     Move.l    (a0)+,(a1)+
  1339.     Dbra    d0,.CopyToBuffer
  1340.     Move.l    a1,sn_BufferCurrent(a4)
  1341.     Bra.s    .Exit
  1342.  
  1343. .RenderToScreen    Move.l    d0,a1
  1344.     Bsr    RenderLineToScreen
  1345.  
  1346. .Exit    Movem.l    (sp)+,d0-d7/a0-a6
  1347.     Rts
  1348.  
  1349.  
  1350.  
  1351.  
  1352. RenderLineToScreen    ; IN: a0.l = ByteBuffer (source)
  1353.     ; IN: a1.l = Ptr to screen
  1354.     ; IN: a4.l = ScreenNode
  1355.     Movem.l    d0-d7/a0-a6,-(sp)
  1356.     Move.w    sn_OutputLine(a4),d1
  1357.     Move.w    sn_PicType(a4),d0          !!!!
  1358.     Cmp.w    #"IF",d0
  1359.     Bne.s    .CheckRest
  1360.     Tst.b    Render+1(a5)
  1361.     Bne.s    .NotInterlaced
  1362.     Addq.w    #1,sn_OutputLine(a4)
  1363.  
  1364.     Move.w    sn_RenderW(a4),d2
  1365.     Bsr    PlanarToPlanar
  1366.     Bra.s    .Exit
  1367.     Beq.s    .NotInterlaced
  1368.  
  1369. .CheckRest    Cmp.w    #"JP",d0
  1370.     Beq.s    .NotInterlaced
  1371.     Cmp.w    #"BM",d0
  1372.     Beq.s    .Backwards
  1373.     Cmp.w    #"PC",d0
  1374.     Beq.s    .NotInterlaced
  1375.     Must be GIF
  1376.     Btst    #6,sn_SpecialInfo+1(a4)
  1377.     Beq.s    .NotInterlaced
  1378.     Move.w    d1,d2
  1379.     Sub.w    FontH(a5),d2
  1380.     Move.b    sn_SpecialInfo(a4),d3
  1381.     Beq.s    .Step8
  1382.     Subq.b    #2,d3
  1383.     Beq.s    .Step4
  1384.     Blt.s    .Step8b
  1385. .Step2    Addq.w    #2,d2
  1386.     Bra.s    .Done
  1387. .Step4    Addq.w    #4,d2
  1388.     Cmp.w    sn_H(a4),d2
  1389.     Blt.s    .Done
  1390.     Addq.b    #1,sn_SpecialInfo(a4)
  1391.     Moveq    #1,d2
  1392.     Bra.s    .Done
  1393. .Step8b    Addq.w    #8,d2
  1394.     Cmp.w    sn_H(a4),d2
  1395.     Blt.s    .Done
  1396.     Addq.b    #1,sn_SpecialInfo(a4)
  1397.     Moveq    #2,d2
  1398.     Bra.s    .Done
  1399. .Step8    Addq.w    #8,d2
  1400.     Cmp.w    sn_H(a4),d2
  1401.     Blt.s    .Done
  1402.     Addq.b    #1,sn_SpecialInfo(a4)
  1403.     Moveq    #4,d2
  1404. .Done    Add.w    FontH(a5),d2
  1405.     Move.w    d2,sn_OutputLine(a4)
  1406.     Bra.s    .DoC2P
  1407. .Backwards    Subq.w    #1,sn_OutputLine(a4)
  1408.     Bra.s    .DoC2P
  1409. .NotInterlaced    Addq.w    #1,sn_OutputLine(a4)
  1410. .DoC2P    Move.w    sn_RenderW(a4),d2
  1411.     Bsr    ChunkyToPlanar
  1412.  
  1413. .Exit    Movem.l    (sp)+,d0-d7/a0-a6
  1414.     Rts
  1415.  
  1416.  
  1417.  
  1418.  
  1419. PlanarToChunky    ; IN: a0.l = Ptr to output buffer
  1420.     ; IN: a2.l = Ptr to planar data
  1421.     ; IN: d0.w = Width of line in pixels
  1422.     ; IN: d3.w = 0: Palette data  1: 24-bit data
  1423.     ;COM: d0-d2/d4-d7 destroyed
  1424.  
  1425.     Movem.l    a0-a5,-(sp)
  1426.     Add.w    #15,d0
  1427.     Lsr.w    #4,d0
  1428.     Add.w    d0,d0
  1429.  
  1430.     Move.w    d0,a1    1x
  1431.     Lea    (a1,d0.w),a5    2x
  1432.     ;        a2 points to BP 0
  1433.     Lea    (a2,a5.l),a3    a3 points to BP 2
  1434.     Lea    (a3,a5.l),a4    a4 points to BP 4
  1435.     Lea    (a4,a5.l),a5    a5 points to BP 6
  1436.  
  1437.     Move.l    #$f0f0f0f0,d6
  1438.     Move.l    #$cccc3333,d7
  1439.     Subq.w    #1,d0
  1440.  
  1441. .Loop    Move.b    (a4,a1.l),d4    BP 5
  1442.     Swap    d4
  1443.     Move.b    (a5,a1.l),d4    BP 7
  1444.     Lsl.l    #8,d4
  1445.     Move.b    (a5)+,d4    BP 6
  1446.     Swap    d4
  1447.     Move.b    (a4)+,d4    BP 4
  1448.  
  1449.     Move.b    (a2,a1.l),d5    BP 1
  1450.     Swap    d5
  1451.     Move.b    (a3,a1.l),d5    BP 3
  1452.     Lsl.l    #8,d5
  1453.     Move.b    (a3)+,d5    BP 2
  1454.     Swap    d5
  1455.     Move.b    (a2)+,d5    BP 0
  1456.  
  1457.     Move.l    d4,d1
  1458.     Move.l    d5,d2
  1459.     And.l    d6,d4
  1460.     And.l    d6,d2
  1461.     Eor.l    d4,d1
  1462.     Eor.l    d2,d5
  1463.     Lsr.l    #4,d2
  1464.     Lsl.l    #4,d1
  1465.     Or.l    d2,d4
  1466.     Or.l    d1,d5
  1467.  
  1468.     Move.l    d4,d1
  1469.     And.l    d7,d4
  1470.     Eor.l    d4,d1
  1471.     Lsr.w    #2,d1
  1472.     Swap    d1
  1473.     Lsl.w    #2,d1
  1474.     Or.l    d1,d4
  1475.  
  1476.     Move.l    d5,d1
  1477.     And.l    d7,d5
  1478.     Eor.l    d5,d1
  1479.     Lsr.w    #2,d1
  1480.     Swap    d1
  1481.     Lsl.w    #2,d1
  1482.     Or.l    d1,d5
  1483.  
  1484.     Move.l    d4,d1
  1485.     And.l    #$aa55aa55,d4
  1486.     Eor.l    d4,d1
  1487.     Lsr.b    #1,d1
  1488.     Rol.w    #8,d1
  1489.     Add.b    d1,d1
  1490.     Swap    d1
  1491.     Lsr.b    #1,d1
  1492.     Rol.w    #8,d1
  1493.     Add.b    d1,d1
  1494.     Swap    d1
  1495.     Or.l    d1,d4
  1496.  
  1497.     Move.l    d5,d1
  1498.     And.l    #$aa55aa55,d5
  1499.     Eor.l    d5,d1
  1500.     Lsr.b    #1,d1
  1501.     Rol.w    #8,d1
  1502.     Add.b    d1,d1
  1503.     Swap    d1
  1504.     Lsr.b    #1,d1
  1505.     Rol.w    #8,d1
  1506.     Add.b    d1,d1
  1507.     Swap    d1
  1508.     Or.l    d1,d5
  1509.  
  1510.     Tst.b    d3
  1511.     Bne.s    .24bit
  1512.     Move.l    d4,(a0)+
  1513.     Move.l    d5,(a0)+
  1514.     Dbra    d0,.Loop
  1515.     Bra.s    .Exit
  1516.  
  1517. .24bit    Move.b    d4,9(a0)
  1518.     Lsr.w    #8,d4
  1519.     Move.b    d4,6(a0)
  1520.     Swap    d4
  1521.     Move.b    d4,3(a0)
  1522.     Lsr.w    #8,d4
  1523.     Move.b    d4,(a0)
  1524.  
  1525.     Move.b    d5,21(a0)
  1526.     Lsr.w    #8,d5
  1527.     Move.b    d5,18(a0)
  1528.     Swap    d5
  1529.     Move.b    d5,15(a0)
  1530.     Lsr.w    #8,d5
  1531.     Move.b    d5,12(a0)
  1532.  
  1533.     Lea    24(a0),a0
  1534.     Dbra    d0,.Loop
  1535.  
  1536. .Exit    Movem.l    (sp)+,a0-a5
  1537.     Rts
  1538.  
  1539.  
  1540.  
  1541.     CNOP    0,4
  1542. HAM8ToRGB    ; IN: a0.l = Ptr to RGB output buffer
  1543.     ; IN: a1.l = Ptr to palette (4 bytes/entry)
  1544.     ; IN: a2.l = Ptr to Palette-line (1 byte/pixel)
  1545.     ; IN: d0.w = Length of Palette-line in pixels
  1546.  
  1547.     Movem.l    a0/a2,-(sp)
  1548.  
  1549.     Moveq    #0,d5
  1550.     Move.b    1(a1),d5
  1551.     Moveq    #0,d6
  1552.     Move.b    2(a1),d6
  1553.     Moveq    #0,d7
  1554.     Move.b    3(a1),d7
  1555.  
  1556.     Subq.w    #1,d0
  1557.  
  1558. .Loop    Moveq    #0,d1
  1559.     Move.b    (a2)+,d1
  1560.     Move.w    d1,d2
  1561.     And.w    #$3f,d1
  1562.     Eor.w    d1,d2
  1563.  
  1564.     Sub.w    #64,d2
  1565.     Beq.s    .Blue
  1566.     Blt.s    .Color
  1567.     Tst.b    d2
  1568.     Blt.s    .Green
  1569. .Red    Lsl.b    #2,d1
  1570.     And.w    #3,d5
  1571.     Or.w    d1,d5
  1572.     Bra.s    .DoLoop
  1573. .Blue    Lsl.b    #2,d1
  1574.     And.w    #3,d7
  1575.     Or.w    d1,d7
  1576.     Bra.s    .DoLoop
  1577. .Green    Lsl.b    #2,d1
  1578.     And.w    #3,d6
  1579.     Or.w    d1,d6
  1580.     Bra.s    .DoLoop
  1581. .Color
  1582.     IFNE    MC68000
  1583.     Lsl.w    #2,d1
  1584.     Move.b    1(a1,d1.w),d5
  1585.     Move.b    2(a1,d1.w),d6
  1586.     Move.b    3(a1,d1.w),d7
  1587.     ELSE
  1588.     Move.b    1(a1,d1.w*4),d5
  1589.     Move.b    2(a1,d1.w*4),d6
  1590.     Move.b    3(a1,d1.w*4),d7
  1591.     ENDC
  1592. .DoLoop    Move.b    d5,(a0)+
  1593.     Move.b    d6,(a0)+
  1594.     Move.b    d7,(a0)+
  1595.     Dbra    d0,.Loop
  1596.  
  1597.     Movem.l    (sp)+,a0/a2
  1598.     Rts
  1599.  
  1600.  
  1601.     CNOP    0,4
  1602. RGBtoGray    ; IN: a0.l = Ptr to RGB buffer (in- and output)
  1603.     ; IN: d0.w = Length of Palette-line in pixels
  1604.  
  1605.     Movem.l    a0-a1,-(sp)
  1606.     Move.l    a0,a1
  1607. .Loop    Moveq    #0,d1
  1608.     Move.b    (a1)+,d1    Red component
  1609.     Move.w    d1,d2
  1610.     Lsl.w    #3,d1
  1611.     Add.w    d1,d2
  1612.  
  1613.     Moveq    #0,d1
  1614.     Move.b    (a1)+,d1    Green component
  1615.     Add.w    d1,d2
  1616.     Add.w    d1,d2
  1617.     Add.w    d1,d2
  1618.     Lsl.w    #4,d1
  1619.     Add.w    d1,d2
  1620.  
  1621.     Moveq    #0,d1
  1622.     Move.b    (a1)+,d1    Blue component
  1623.     Lsl.w    #2,d1
  1624.     Add.w    d1,d2
  1625.  
  1626.     Add.w    #16,d2
  1627.     Lsr.w    #5,d2
  1628.     Move.b    d2,(a0)+
  1629.  
  1630.     Dbra    d0,.Loop
  1631.  
  1632.     ;R:G:B = 9:19:4 (32) => 281:594:125
  1633.     ;R:G:B = 290:597:113 
  1634.  
  1635.     Movem.l    (sp)+,a0-a1
  1636.     Rts
  1637.  
  1638.  
  1639.  
  1640.     CNOP    0,4
  1641. PaletteToRGB    ; IN: a0.l = Ptr to RGB output buffer
  1642.     ; IN: a1.l = Ptr to palette (4 bytes/entry)
  1643.     ; IN: a2.l = Ptr to Palette-line (1 byte/pixel)
  1644.     ; IN: d0.w = Length of Palette-line in pixels
  1645.     ;COM: d0-d4 destroyed
  1646.  
  1647.     Movem.l    a0/a2,-(sp)
  1648.     Moveq    #0,d1
  1649.  
  1650.     Tst.b    HalveWidth(a5)
  1651.     Beq.s    .Loop2
  1652.     Move.l    #$fefefe,d5
  1653.     Addq.w    #1,d0
  1654.     Lsr.w    #1,d0
  1655.     Subq.w    #1,d0
  1656.  
  1657. .LoopDownScaleBy2    Move.b    (a2)+,d1    Color Number
  1658.     IFNE    MC68000
  1659.     Lsl.w    #2,d1
  1660.     Move.l    (a1,d1.w),d3
  1661.     Moveq    #0,d1
  1662.     ELSE
  1663.     Move.l    (a1,d1.w*4),d3
  1664.     ENDC
  1665.     And.l    d5,d3
  1666.     Move.b    (a2)+,d1
  1667.     IFNE    MC68000
  1668.     Lsl.w    #2,d1
  1669.     Move.l    (a1,d1.w),d4
  1670.     Moveq    #0,d1
  1671.     ELSE
  1672.     Move.l    (a1,d1.w*4),d4
  1673.     ENDC
  1674.     And.l    d5,d4
  1675.  
  1676.     Add.l    d4,d3
  1677.     Lsr.l    #1,d3
  1678.  
  1679.     IFNE    MC68000
  1680.     Move.b    d3,2(a0)
  1681.     Lsr.w    #8,d3
  1682.     Move.b    d3,1(a0)
  1683.     Swap    d3
  1684.     Move.b    d3,(a0)
  1685.     ELSE
  1686.     Move.w    d3,1(a0)
  1687.     Swap    d3
  1688.     Move.b    d3,(a0)
  1689.     ENDC
  1690.     Addq.l    #3,a0
  1691.     Dbra    d0,.LoopDownScaleBy2
  1692.     Bra.s    .GoOn
  1693.  
  1694. .Loop2    Subq.w    #1,d0
  1695. .Loop    Move.b    (a2)+,d1
  1696.     IFNE    MC68000
  1697.     Lsl.w    #2,d1
  1698.     Move.b    1(a1,d1.w),(a0)+
  1699.     Move.b    2(a1,d1.w),(a0)+
  1700.     Move.b    3(a1,d1.w),(a0)+
  1701.     Moveq    #0,d1
  1702.     ELSE
  1703.     Move.b    1(a1,d1.w*4),(a0)+
  1704.     Move.w    2(a1,d1.w*4),(a0)+
  1705.     ENDC
  1706.     Dbra    d0,.Loop
  1707.  
  1708. .GoOn    Clr.b    (a0)+
  1709.     Clr.b    (a0)+
  1710.     Clr.b    (a0)+
  1711.  
  1712.     Movem.l    (sp)+,a0/a2
  1713.     Rts
  1714.  
  1715.  
  1716.  
  1717.     CNOP    0,4
  1718. PaletteToGray    ; IN: a0.l = Ptr to Gray output buffer
  1719.     ; IN: a1.l = Ptr to palette (4 bytes/entry)
  1720.     ; IN: a2.l = Ptr to Palette-line (1 byte/pixel)
  1721.     ; IN: d0.w = Length of Palette-line in pixels
  1722.     ;COM: d0-d4 destroyed
  1723.  
  1724.     Movem.l    a0/a2,-(sp)
  1725.     Moveq    #0,d1
  1726.  
  1727.     Subq.w    #1,d0
  1728. .Loop    Move.b    (a2)+,d1
  1729.     Move.b    (a1,d1.w),(a0)+
  1730.     Dbra    d0,.Loop
  1731.  
  1732. .GoOn    Clr.b    (a0)+
  1733.  
  1734.     Movem.l    (sp)+,a0/a2
  1735.     Rts
  1736.  
  1737.  
  1738.  
  1739.     CNOP    0,4
  1740. HalveRGB    ; IN: a0.l = RGB Buffer (3 bytes/pixel)
  1741.     ; IN: d0.w = Number of pixels in RGB Buffer
  1742.  
  1743.     Movem.l    a0-a1,-(sp)
  1744.     Move.l    a0,a1
  1745.     Move.l    #$fefefe,d7
  1746.     Addq.w    #1,d0
  1747.     Lsr.w    #1,d0
  1748.     Subq.w    #1,d0
  1749.  
  1750. .Loop    Move.l    (a0),d1
  1751.     Lsr.l    #8,d1
  1752.     Addq.l    #2,a0
  1753.     And.l    d7,d1
  1754.     Move.l    (a0)+,d2
  1755.     And.l    d7,d2
  1756.  
  1757.     Add.l    d1,d2
  1758.     Lsr.l    #1,d2
  1759.  
  1760.     IFNE    MC68000
  1761.     Move.b    d2,2(a1)
  1762.     Lsr.w    #8,d2
  1763.     Move.b    d2,1(a1)
  1764.     Swap    d2
  1765.     Move.b    d2,(a1)
  1766.     ELSE
  1767.     Move.w    d2,1(a1)
  1768.     Swap    d2
  1769.     Move.b    d2,(a1)
  1770.     ENDC
  1771.     Addq.l    #3,a1
  1772.     Dbra    d0,.Loop
  1773.  
  1774.     Movem.l    (sp)+,a0-a1
  1775.     Rts
  1776.  
  1777.  
  1778.  
  1779.  
  1780. ;RGBScaler    ; IN: a0.l = Ptr to RGB line (3 words/color)
  1781. ;    Movem.l    d0-d7/a0-a3,-(sp)
  1782. ;    Move.w    PicW(a5),d1
  1783. ;    Move.w    ScaleLevel(a5),d0
  1784. ;    Move.w    d0,d7
  1785. ;    Move.l    a0,a1
  1786. ;
  1787. ;    Lea    ScaleTable(pc),a2
  1788. ;    Move.w    VerScale(a5),d2
  1789. ;    Add.w    d0,d2
  1790. ;    Cmp.w    #16,d2
  1791. ;    Bge.s    .ScaleIt
  1792. ;    Move.w    d2,VerScale(a5)
  1793. ;    Bra    .Exit
  1794. ;
  1795. ;.ScaleIt    Sub.w    #16,d2
  1796. ;    Move.w    d2,VerScale(a5)
  1797. ;
  1798. ;.Scale    Moveq    #16,d2
  1799. ;    Sub.w    d7,d2
  1800. ;    Move.w    (a0)+,d3
  1801. ;    Move.w    (a0)+,d4
  1802. ;    Move.w    (a0)+,d5
  1803. ;    Move.l    (a2,d7.w*4),a3
  1804. ;    Move.w    (a3,d3.w*2),d3
  1805. ;    Move.w    (a3,d4.w*2),d4
  1806. ;    Move.w    (a3,d5.w*2),d5
  1807. ;    Subq.w    #1,d1
  1808. ;    Cmp.w    d0,d2
  1809. ;    Bge.s    .Again
  1810. ;    Bra.s    .Lower
  1811. ;
  1812. ;.Again    Sub.w    d0,d2
  1813. ;    Move.l    (a2,d0.w*4),a3
  1814. ;
  1815. ;    Move.w    (a0)+,d6
  1816. ;    Add.w    (a3,d6.w*2),d3
  1817. ;    Move.w    (a0)+,d6
  1818. ;    Add.w    (a3,d6.w*2),d4
  1819. ;    Move.w    (a0)+,d6
  1820. ;    Add.w    (a3,d6.w*2),d5
  1821. ;    Subq.w    #1,d1
  1822. ;    Cmp.w    d0,d2
  1823. ;    Bge.s    .Again
  1824. ;
  1825. ;.Lower    Tst.w    d2
  1826. ;    Beq.s    .Skip
  1827. ;    Move.l    (a2,d2.w*4),a3
  1828. ;    Move.w    (a0),d6
  1829. ;    Add.w    (a3,d6.w*2),d3
  1830. ;    Move.w    2(a0),d6
  1831. ;    Add.w    (a3,d6.w*2),d4
  1832. ;    Move.w    4(a0),d6
  1833. ;    Add.w    (a3,d6.w*2),d5
  1834. ;
  1835. ;.Skip    Move.w    d0,d7
  1836. ;    Sub.w    d2,d7
  1837. ;
  1838. ;    Lsr.w    #4,d3
  1839. ;    Lsr.w    #4,d4
  1840. ;    Lsr.w    #4,d5
  1841. ;
  1842. ;    Move.w    d3,(a1)+
  1843. ;    Move.w    d4,(a1)+
  1844. ;    Move.w    d5,(a1)+
  1845. ;
  1846. ;.Skip3    Tst.w    d1
  1847. ;    Bgt    .Scale
  1848. ;    Moveq    #0,d0
  1849. ;    Bra.s    .Exit2
  1850. ;
  1851. ;.Exit    Moveq    #-1,d0
  1852. ;.Exit2    Movem.l    (sp)+,d0-d7/a0-a3
  1853. ;    Rts
  1854.  
  1855.  
  1856.     CNOP    0,4
  1857. RGBScalerSimple    ; IN: a0.l = Ptr to RGB line (3 bytes/color)
  1858.     ; IN: d1.w = Width of RGB line
  1859.     Movem.l    d0-d2/a0-a1,-(sp)
  1860.     Move.w    ScaleLevel(a5),d0
  1861.     Move.l    a0,a1
  1862.  
  1863.     ;Add.w    d0,VerScale(a5)
  1864.     ;Blt.s    .Exit
  1865.     ;Sub.w    #64,VerScale(a5)
  1866.  
  1867. .ScaleIt    Subq.w    #1,d1
  1868.     Moveq    #-32,d2
  1869.  
  1870. .Scale    Add.w    d0,d2
  1871.     Blt.s    .SkipThisOne
  1872.     Sub.w    #64,d2
  1873.     IFNE    MC68000
  1874.     Move.b    (a0)+,(a1)+
  1875.     Move.b    (a0)+,(a1)+
  1876.     Move.b    (a0)+,(a1)+
  1877.     ELSE
  1878.     Move.w    (a0)+,(a1)+
  1879.     Move.b    (a0)+,(a1)+
  1880.     ENDC
  1881.     Dbra    d1,.Scale
  1882.     Bra.s    .End
  1883. .SkipThisOne    Addq.l    #3,a0
  1884.     Bra.s    .Scale
  1885.  
  1886. .End    Moveq    #0,d0
  1887. .Exit    Movem.l    (sp)+,d0-d2/a0-a1
  1888.     Rts
  1889.  
  1890.  
  1891.  
  1892.     CNOP    0,4
  1893. GrayScalerSimple    ; IN: a0.l = Ptr to Grayline (1 byte/color)
  1894.     ; IN: d1.w = Width of Gray line
  1895.     Movem.l    d0-d2/a0-a1,-(sp)
  1896.     Move.w    ScaleLevel(a5),d0
  1897.     Move.l    a0,a1
  1898.  
  1899.     ;Add.w    d0,VerScale(a5)
  1900.     ;Blt.s    .Exit
  1901.     ;Sub.w    #64,VerScale(a5)
  1902.  
  1903. .ScaleIt    Subq.w    #1,d1
  1904.     Moveq    #-32,d2
  1905.  
  1906. .Scale    Add.w    d0,d2
  1907.     Blt.s    .SkipThisOne
  1908.     Sub.w    #64,d2
  1909.     Move.b    (a0)+,(a1)+
  1910.     Dbra    d1,.Scale
  1911.     Bra.s    .End
  1912. .SkipThisOne    Addq.l    #1,a0
  1913.     Bra.s    .Scale
  1914.  
  1915. .End    Moveq    #0,d0
  1916. .Exit    Movem.l    (sp)+,d0-d2/a0-a1
  1917.     Rts
  1918.  
  1919.  
  1920.  
  1921.     CNOP    0,4
  1922. PaletteScalerSimple    ; IN: a0.l = Ptr to Palette line (1 byte/pixel)
  1923.     ; IN: d1.w = Width of palette line
  1924.     Movem.l    d0-d2/a0-a1,-(sp)
  1925.     Move.w    ScaleLevel(a5),d0
  1926.     Move.l    a0,a1
  1927.  
  1928.     ;Add.w    d0,VerScale(a5)
  1929.     ;Blt.s    .Exit
  1930.     ;Sub.w    #64,VerScale(a5)
  1931.  
  1932. .ScaleIt    Subq.w    #1,d1
  1933.     Moveq    #-32,d2
  1934.  
  1935. .Scale    Add.w    d0,d2
  1936.     Blt.s    .SkipThisOne
  1937.     Sub.w    #64,d2
  1938.     Move.b    (a0)+,(a1)+
  1939.     Dbra    d1,.Scale
  1940.     Bra.s    .End
  1941. .SkipThisOne    Addq.l    #1,a0
  1942.     Bra.s    .Scale
  1943.  
  1944. .End    Moveq    #0,d0
  1945. .Exit    Movem.l    (sp)+,d0-d2/a0-a1
  1946.     Rts
  1947.  
  1948.  
  1949.  
  1950.     CNOP    0,4
  1951. RGBtoBWdither    ; IN: a0.l = Ptr to Gray line (1 byte/color) (unscaled)
  1952.     ; IN: a1.l = Ptr to output buffer
  1953.     ; IN: d0.w = Length of RGB in pixels
  1954.     ; IN: d1.w = Shift final output data d1 bits to right
  1955.  
  1956.     ;COM: d0-d2 destroyed
  1957.     Movem.l    a0-a3,-(sp)
  1958.  
  1959.     Subq.w    #1,d0
  1960.     Move.l    Floyd1(a5),a2
  1961.     Move.l    Floyd2(a5),a3
  1962.     Move.l    a3,Floyd1(a5)
  1963.     Move.l    a2,Floyd2(a5)
  1964.  
  1965.     Moveq    #0,d2
  1966.     Clr.w    (a3)
  1967.     Moveq    #8,d4
  1968.     Sub.w    d1,d4
  1969.  
  1970. .Loop    Moveq    #0,d3
  1971.     Move.b    (a0)+,d3
  1972.  
  1973.     Add.w    (a2)+,d3
  1974.     Bge.s    .OkA
  1975.     Moveq    #0,d3
  1976. .OkA    Cmp.w    #255,d3
  1977.     Ble.s    .OkA1
  1978.     Move.w    #255,d3
  1979.  
  1980. .OkA1    Move.w    d3,d2
  1981.     Lsr.w    d1,d2
  1982.     Move.b    d2,(a1)+
  1983.     Move.w    d3,d5
  1984.     Lsr.w    d4,d5
  1985.     Lsl.w    d1,d2
  1986.     Or.w    d5,d2
  1987.  
  1988.     ;d3 = Color needed   d2 = Color chosen
  1989.  
  1990.     Sub.w    d2,d3
  1991.     Asr.w    #2,d3
  1992.     Add.w    d3,(a2)
  1993.     Add.w    d3,-2(a3)
  1994.     Add.w    d3,(a3)+
  1995.     Move.w    d3,(a3)
  1996.  
  1997.     Dbra    d0,.Loop
  1998.  
  1999.     Movem.l    (sp)+,a0-a3
  2000.     Rts
  2001.  
  2002.  
  2003.  
  2004.     CNOP    0,4
  2005. RGBtoBW    ; IN: a0.l = Ptr to RGB line (1 byte/color) (unscaled)
  2006.     ; IN: a1.l = Ptr to output buffer
  2007.     ; IN: d0.w = Length of RGB in pixels
  2008.     ; IN: d1.w = Shift final output data d1 bits to right
  2009.     ;COM: d0/d2 destroyed
  2010.     Movem.l    a0-a1,-(sp)
  2011.     Subq.w    #1,d0
  2012.     Moveq    #0,d2
  2013.  
  2014. .Loop    Move.b    (a0)+,d2
  2015.     Lsr.w    d1,d2
  2016.     Move.b    d2,(a1)+
  2017.     Dbra    d0,.Loop
  2018.  
  2019.     Movem.l    (sp)+,a0-a1
  2020.     Rts
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026. ;    CNOP    0,4
  2027. ;PlanarToPlanar    ; IN: a0.l = Ptr to planar-data
  2028. ;    ; IN: a1.l = Ptr to Screen
  2029. ;    ; IN: a4.l = ScreenNode
  2030. ;    ; IN: d1.w = OutputLine
  2031. ;    ; IN: d2.w = RenderW
  2032. ;
  2033. ;    Add.w    #15,d2
  2034. ;    Lsr.w    #4,d2
  2035. ;    Subq.w    #1,d2
  2036. ;
  2037. ;    Move.l    88(a1),a2    a2 = bitmap
  2038. ;    Moveq    #0,d3
  2039. ;    Move.b    5(a2),d3
  2040. ;    Subq.w    #1,d3
  2041. ;    Mulu    (a2),d1    BytesPerRow * OutputLine
  2042. ;    Addq.l    #8,a2
  2043. ;
  2044. ;.BPLoop    Move.l    (a2)+,a1
  2045. ;    Add.l    d1,a1
  2046. ;    Move.w    d2,d0
  2047. ;.XLoop    Move.w    (a0)+,(a1)+
  2048. ;    Dbra    d0,.XLoop
  2049. ;    Dbra    d3,.BPLoop
  2050. ;
  2051. ;    Rts
  2052.